package com.uvstu.system.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSONObject;
import com.uvstu.common.core.domain.entity.SysUser;
import com.uvstu.common.pay.client.AliPayClient;
import com.uvstu.common.pay.client.WxPayClient;
import com.uvstu.common.utils.SecurityUtils;
import com.uvstu.system.domain.SApplication;
import com.uvstu.system.domain.SGood;
import com.uvstu.system.service.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.uvstu.common.annotation.Log;
import com.uvstu.common.core.controller.BaseController;
import com.uvstu.common.core.domain.AjaxResult;
import com.uvstu.common.enums.BusinessType;
import com.uvstu.system.domain.SOrder;
import com.uvstu.common.utils.poi.ExcelUtil;
import com.uvstu.common.core.page.TableDataInfo;

import static java.lang.Thread.sleep;

/**
 * 订单Controller
 * 
 * @author 郑伟滨
 * @date 2023-02-01
 */
@RestController
@RequestMapping("/system/order")
public class SOrderController extends BaseController
{
    @Autowired
    private ISOrderService sOrderService;

    @Autowired
    private ISGoodService sGoodService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISApplicationService applicationService;

    /**
     * 查询订单列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:list')")
    @GetMapping("/list")
    public TableDataInfo list(SOrder sOrder)
    {
        startPage();
        List<SOrder> list = sOrderService.selectSOrderList(sOrder);
        return getDataTable(list);
    }

    /**
     * 导出订单列表
     */
    @PreAuthorize("@ss.hasPermi('system:order:export')")
    @Log(title = "订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SOrder sOrder)
    {
        List<SOrder> list = sOrderService.selectSOrderList(sOrder);
        ExcelUtil<SOrder> util = new ExcelUtil<SOrder>(SOrder.class);
        util.exportExcel(response, list, "订单数据");
    }

    /**
     * 获取订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:order:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(sOrderService.selectSOrderById(id));
    }

    /**
     * 新增订单
     */
    @PreAuthorize("@ss.hasPermi('system:order:add')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SOrder sOrder)
    {
        return toAjax(sOrderService.insertSOrder(sOrder));
    }

    /**
     * 修改订单
     */
    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SOrder sOrder)
    {
        return toAjax(sOrderService.updateSOrder(sOrder));
    }

    /**
     * 删除订单
     */
    @PreAuthorize("@ss.hasPermi('system:order:remove')")
    @Log(title = "订单", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(sOrderService.deleteSOrderByIds(ids));
    }


    /**
     * 用户订单列表
     * @param sOrder
     * @return
     */
    @GetMapping("/getUserOrderList")
    public TableDataInfo getUserOrderList(SOrder sOrder)
    {
        startPage();
        SysUser user = SecurityUtils.getLoginUser().getUser();
        sOrder.setUserId(user.getUserId());
        List<SOrder> list = sOrderService.selectSOrderList(sOrder);
        return getDataTable(list);
    }

    /**
     * 获取用户最新可用订单
     * @return
     */
    @GetMapping("/getUserOrder")
    public SOrder getUserOrder()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        SOrder sOrder = new SOrder();
        sOrder.setUserId(user.getUserId());
        sOrder.setStatus(2);
        List<SOrder> list = sOrderService.selectSOrderList(sOrder);
        if(list.size() != 0){
            return list.get(0);
        }else{
            return null;
        }
    }

    /**
     * 关闭订单
     * @return
     */
    @GetMapping("/closeOrder")
    public boolean closeOrder(SOrder sOrder)
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        sOrder = sOrderService.selectSOrderById(sOrder.getId());
        if(sOrder != null){
            if(sOrder.getUserId() == user.getUserId()){
                //执行删除订单
                sOrderService.deleteSOrderById(sOrder.getId());
                return true;
            }
        }
        return false;
    }

    /**
     * 订单解绑
     * @return
     */
    @GetMapping("/relieveOrder")
    public boolean relieveOrder(SOrder sOrder)
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        sOrder = sOrderService.selectSOrderById(sOrder.getId());
        if(sOrder != null){
            if(sOrder.getUserId() == user.getUserId() && sOrder.getStatus() == 2){
                sOrder.setStatus(7);
                sOrderService.updateSOrder(sOrder);
                //所有应用停止
                SApplication sApplication = new SApplication();
                sApplication.setUserId(user.getUserId());
                sApplication.setStatus(1);
                applicationService.updateSApplicationStatus(sApplication);
                return true;
            }
        }
        return false;
    }

    /**
     * 商品支付宝下单
     */
    @PostMapping("/aliPay")
    public String aliPay(SGood sGood){
        Integer num = sGood.getEffectiveTime();
        //查询商品详情
        sGood = sGoodService.selectSGoodById(sGood.getId());
        num = num * sGood.getEffectiveTime();
        try{
            SysUser user = SecurityUtils.getLoginUser().getUser();
            SOrder sOrder = new SOrder();
            String orderId = String.valueOf(System.currentTimeMillis());
            sOrder.setOrderId(orderId);
            sOrder.setPrice(sGood.getPrice().multiply(new BigDecimal(num)));
            sOrder.setUserId(user.getUserId());
            sOrder.setGoodId(sGood.getId());
            sOrder.setGoodName(sGood.getGoodName());
            sOrder.setPayChannel(sGood.getPayChannel());
            sOrder.setAppNum(sGood.getAppNum());
            sOrder.setPayMethod(1);
            sOrder.setEndTime(subMonth(new Date(),num));
            sOrder.setRate(sGood.getRate());
            //查询当前用户是否有存在订单，有则判断商品是否一致，一致则是续费，否则则是升级
            SOrder oldOrder = new SOrder();
            oldOrder.setUserId(user.getUserId());
            oldOrder.setStatus(2);
            List<SOrder> sOrderList = sOrderService.selectUserOrder(oldOrder);
            if(sOrderList.size() != 0){
                if(sOrderList.get(0).getGoodId() == sGood.getId()){
                    //续费
                    sOrder.setGoodName("[续费]"+sGood.getGoodName());
                    sGood.setGoodName("[续费]"+sGood.getGoodName());
                    //时间重计
                    sOrder.setEndTime(subMonth(sOrderList.get(0).getEndTime(),num));
                }else{
                    //升级
                    SGood oldGood = sGoodService.selectSGoodById(sOrderList.get(0).getGoodId());
                    //计算时间差价
                    Calendar calendar = Calendar.getInstance();
                    //获取当前月份
                    int month = calendar.get(Calendar.MONTH) + 1;
                    //获取到期月份
                    int endMonth = sOrderList.get(0).getEndTime().getMonth()+1;
                    BigDecimal price = sGood.getPrice().subtract(oldGood.getPrice());
                    sOrder.setPrice(price.multiply(new BigDecimal((endMonth-month)==0?1:(endMonth-month))));
                    //赋值到期时间
                    sOrder.setEndTime(sOrderList.get(0).getEndTime());
                    sOrder.setGoodName("[升级]"+sGood.getGoodName());
                    sGood.setGoodName("[升级]"+sGood.getGoodName());
                }
            }
            sOrderService.insertSOrder(sOrder);
            return configService.selectConfigByKey("sys.url")+"/open/pay/api/getWxQrcode?url="
                    +AliPayClient.qrPay(orderId,sOrder.getPrice().toString(),sGood.getGoodName());
        }catch (Exception e){
            //支付宝通道支付失败，请联系管理员
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 支付宝退款
     * @param sOrder
     */
    @RequestMapping("/zfbRefund")
    public boolean zfbRefund(SOrder sOrder){
        //订单号
        sOrder = sOrderService.selectSOrderById(sOrder.getId());
        if(!isNow(sOrder.getCreateTime())){
            return false;
        }
        //扣除手续费
        BigDecimal price = new BigDecimal(0);
        if(sOrder.getPrice().compareTo(new BigDecimal(1)) != -1){
            price = sOrder.getPrice().multiply(new BigDecimal(0.994)).setScale(2, RoundingMode.HALF_UP);
        }else{
            price = sOrder.getPrice();
        }
        try{
            Map<String,Object> map = AliPayClient.refund(sOrder.getOrderId(),sOrder.getTradeNo(),String.valueOf(price),"平台退款(已扣除平台交易手续费)");
            if(map.get("alipay_trade_refund_response") != null){
                String result = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_refund_response"))).getString("msg");
                if("Success".equals(result)){
                    sOrder.setStatus(5);
                    sOrderService.updateSOrder(sOrder);
                    //更新所有的应用的支付通道
                    SApplication sApplication = new SApplication();
                    sApplication.setStatus(1);
                    sApplication.setUserId(sOrder.getUserId());
                    applicationService.updateSApplicationStatus(sApplication);
                }
            }
            return true;
        }catch (Exception e){
            //支付宝退款失败，请联系管理员
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 商品微信下单
     */
    @PostMapping("/wxPay")
    public String wxPay(SGood sGood){
        Integer num = sGood.getEffectiveTime();
        sGood = sGoodService.selectSGoodById(sGood.getId());
        num = num * sGood.getEffectiveTime();
        try{
            SysUser user = SecurityUtils.getLoginUser().getUser();
            SOrder sOrder = new SOrder();
            String orderId = String.valueOf(System.currentTimeMillis());
            sOrder.setOrderId(orderId);
            sOrder.setPrice(sGood.getPrice().multiply(new BigDecimal(num)));
            sOrder.setUserId(user.getUserId());
            sOrder.setGoodId(sGood.getId());
            sOrder.setGoodName(sGood.getGoodName());
            sOrder.setPayChannel(sGood.getPayChannel());
            sOrder.setAppNum(sGood.getAppNum());
            sOrder.setPayMethod(2);
            sOrder.setEndTime(subMonth(new Date(),num));
            sOrder.setRate(sGood.getRate());
            //查询当前用户是否有存在订单，有则判断商品是否一致，一致则是续费，否则则是升级
            SOrder oldOrder = new SOrder();
            oldOrder.setUserId(user.getUserId());
            oldOrder.setStatus(2);
            List<SOrder> sOrderList = sOrderService.selectUserOrder(oldOrder);
            if(sOrderList.size() != 0){
                if(sOrderList.get(0).getGoodId() == sGood.getId()){
                    //续费
                    sOrder.setGoodName("[续费]"+sGood.getGoodName());
                    sGood.setGoodName("[续费]"+sGood.getGoodName());
                    //时间重计
                    sOrder.setEndTime(subMonth(sOrderList.get(0).getEndTime(),num));
                }else{
                    //升级
                    SGood oldGood = sGoodService.selectSGoodById(sOrderList.get(0).getGoodId());
                    //计算时间差价
                    Calendar calendar = Calendar.getInstance();
                    //获取当前月份
                    int month = calendar.get(Calendar.MONTH) + 1;
                    //获取到期月份
                    int endMonth = sOrderList.get(0).getEndTime().getMonth()+1;
                    BigDecimal price = sGood.getPrice().subtract(oldGood.getPrice());
                    sOrder.setPrice(price.multiply(new BigDecimal((endMonth-month)==0?1:(endMonth-month))));
                    //赋值到期时间
                    sOrder.setEndTime(sOrderList.get(0).getEndTime());
                    sOrder.setGoodName("[升级]"+sGood.getGoodName());
                    sGood.setGoodName("[升级]"+sGood.getGoodName());
                }
            }
            sOrderService.insertSOrder(sOrder);
            int price = (int)(Double.valueOf(sOrder.getPrice().toString())*100);
            Map<String, String> map = WxPayClient.pay(orderId,sGood.getGoodName(),String.valueOf(price));
            //返回拼接的地址
            if(map.get("code_url") != null){
                return configService.selectConfigByKey("sys.url")+"/open/pay/api/getWxQrcode?url="+map.get("code_url").toString();
            }
        }catch (Exception e){
            //微信通道支付失败，请联系管理员
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信退款
     * @param sOrder
     */
    @RequestMapping("/wxRefund")
    public boolean wxRefund(SOrder sOrder){
        //订单号
        sOrder = sOrderService.selectSOrderById(sOrder.getId());
        if(!isNow(sOrder.getCreateTime())){
            return false;
        }
        try{
            int price = (int)(Double.valueOf(sOrder.getPrice().toString())*100);
            Map<String, String> map = WxPayClient.refund(sOrder.getTradeNo(),sOrder.getOrderId(),String.valueOf(price),String.valueOf(price),"全额退款");
            sOrder.setRefundId(map.get("refund_id"));
            sOrder.setStatus(4);
            sOrderService.updateSOrder(sOrder);
            return true;
        }catch (Exception e){
            //微信退款失败，请联系管理员
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 订单同步
     */
    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @RequestMapping("/orderSyn")
    public void orderSyn(){
        Thread thread = new Thread(new Runnable(){
            @Override
            public void run() {
                try{
                    //执行支付支付订单和退款订单
                    SOrder sOrder = new SOrder();
                    sOrder.setStatus(1);
                    List<SOrder> payOrder = sOrderService.selectOrderData(sOrder);
                    updataPayOrder(payOrder);
                    sOrder.setStatus(4);
                    List<SOrder> refundOrder = sOrderService.selectOrderData(sOrder);
                    updataRefundOrder(refundOrder);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }

    /**
     * 支付订单同步
     * @param sOrder
     */
    public void updataPayOrder(List<SOrder> sOrder){
        for (int i = 0; i < sOrder.size(); i++) {
            switch (sOrder.get(i).getPayMethod()){
                case 1:
                    try{
                        Map<String,Object> map = AliPayClient.payQuery(sOrder.get(i).getOrderId(),sOrder.get(i).getTradeNo());
                        if(map.get("alipay_trade_query_response") != null){
                            JSONObject result = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_query_response")));
                            if("TRADE_SUCCESS".equals(result.getString("trade_status"))){
                                if(sOrder.get(i).getGoodName().indexOf("[续费]") != -1){
                                    sOrder.get(i).setGoodName(sOrder.get(i).getGoodName().replace("[续费]",""));
                                    //续费处理
                                    SOrder oldOrder = new SOrder();
                                    oldOrder.setUserId(sOrder.get(i).getUserId());
                                    oldOrder.setStatus(2);
                                    //获取用户可用订单
                                    List<SOrder> sOrderList = sOrderService.selectUserOrder(oldOrder);
                                    if(sOrderList.size() != 0){
                                        //之前订单失效
                                        oldOrder = sOrderList.get(0);
                                        oldOrder.setStatus(7);
                                        sOrderService.updateSOrder(oldOrder);
                                        //当前订单生效
                                        sOrder.get(i).setTradeNo(result.getString("trade_no"));
                                        sOrder.get(i).setStatus(2);
                                        sOrderService.updateSOrder(sOrder.get(i));
                                    }else{
                                        sOrder.get(i).setStatus(2);
                                        sOrder.get(i).setTradeNo(result.getString("trade_no"));
                                        sOrderService.updateSOrder(sOrder.get(i));
                                    }
                                }else{
                                    //支付成功
                                    sOrder.get(i).setStatus(2);
                                    sOrder.get(i).setTradeNo(result.getString("trade_no"));
                                    sOrderService.updateSOrder(sOrder.get(i));
                                }
                                //更新用户应用支付方式
                                SApplication sApplication = new SApplication();
                                sApplication.setPayMethod(Integer.valueOf(sOrder.get(i).getPayChannel()));
                                sApplication.setUserId(sOrder.get(i).getUserId());
                                applicationService.updateSApplicationPayMethod(sApplication);
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    try{
                        Map<String,String> result = WxPayClient.payQuery(sOrder.get(i).getTradeNo());
                        if("SUCCESS".equals(result.get("trade_state"))){
                            if(sOrder.get(i).getGoodName().indexOf("续费") != -1){
                                sOrder.get(i).setGoodName(sOrder.get(i).getGoodName().replace("-续费",""));
                                //续费处理
                                SOrder oldOrder = new SOrder();
                                oldOrder.setUserId(sOrder.get(i).getUserId());
                                oldOrder.setStatus(2);
                                //获取用户可用订单
                                List<SOrder> sOrderList = sOrderService.selectUserOrder(oldOrder);
                                if(sOrderList.size() != 0){
                                    //之前订单失效
                                    oldOrder = sOrderList.get(0);
                                    oldOrder.setStatus(7);
                                    sOrderService.updateSOrder(oldOrder);
                                    //当前订单生效
                                    sOrder.get(i).setStatus(2);
                                    sOrderService.updateSOrder(sOrder.get(i));
                                }else{
                                    sOrder.get(i).setStatus(2);
                                    sOrderService.updateSOrder(sOrder.get(i));
                                }
                            }else{
                                //支付成功
                                sOrder.get(i).setStatus(2);
                                sOrderService.updateSOrder(sOrder.get(i));
                            }
                            //更新用户应用支付方式
                            SApplication sApplication = new SApplication();
                            sApplication.setPayMethod(Integer.valueOf(sOrder.get(i).getPayChannel()));
                            sApplication.setUserId(sOrder.get(i).getUserId());
                            applicationService.updateSApplicationPayMethod(sApplication);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    /**
     * 退款订单同步
     * @param sOrder
     */
    public void updataRefundOrder(List<SOrder> sOrder){
        for (int i = 0; i < sOrder.size(); i++) {
            switch (sOrder.get(i).getPayMethod()){
                case 1:
                    try{
                        Map<String,Object> map = AliPayClient.refundQuery(sOrder.get(i).getOrderId(),sOrder.get(i).getTradeNo());
                        if(map.get("alipay_trade_fastpay_refund_query_response") != null){
                            JSONObject result = JSONObject.parseObject(JSONObject.toJSONString(map.get("alipay_trade_fastpay_refund_query_response")));
                            if("REFUND_SUCCESS".equals(result.getString("refund_status"))){
                                //退款成功
                                sOrder.get(i).setStatus(5);
                                sOrderService.updateSOrder(sOrder.get(i));
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    try{
                        Map<String,String> result = WxPayClient.refundQuery(sOrder.get(i).getRefundId());
                        if("SUCCESS".equals(result.get("result_code"))){
                            //支付成功
                            sOrder.get(i).setStatus(5);
                            sOrderService.updateSOrder(sOrder.get(i));
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }

    /****
     * 传入具体日期 ，返回具体日期增加一个月。
     * @param date 日期(2017-04-13)
     * @return 2017-05-13
     * @throws Exception
     */
    private Date subMonth(Date date,Integer month) throws Exception {
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MONTH, month);
        Date dt1 = rightNow.getTime();
        return dt1;
    }

    /**
     * 判断是否是今天
     * @param date
     * @return
     */
    public static boolean isNow(Date date) {
        Date now = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        String nowDay = sf.format(now);
        String day = sf.format(date);
        return day.equals(nowDay);
    }
}
